/* Fluids: The 3D Navier-Stokes Solve
   Defini��o dos poss�veis valores do flag de uma dada c�lula (Obstacle, South,North, Slip, NoSlip, ....)
   class Scene: cont�m a defini��o da cena (numero de n�s no grid, espacamento, ...)
*/

#ifndef TYPEN_INCLUDED
#define TYPEN_INCLUDED
#include <math.h>
#include <stdio.h>
#include <assert.h>
#include <float.h>

#ifndef TRUE
#define TRUE  1
#endif
#ifndef FALSE
#define FALSE 0
#endif

#define min(x,y)    ((x) < (y)?(x):(y))

enum {
  
 
   //SLIP      = 0x0002,        // =2;    Rutschbedingung; caracter escorregadio
   //INOUT     = 0x0004,        // =4;    Ein- bzw. Ausstroemzelle 
   //NORTH     = 0x0008,        // =8;    noerdl. Zelle Fluid 
   //SOUTH     = 0x0010,        // =16;   suedl.    "     "   
   //EAST      = 0x0020,        // =32;   oestl.    "     "   
   //WEST      = 0x0040,        // =64;   westl.    "     "   
   //TOP       = 0x0080,        // =128;  obere     "     "   
   //BOTTOM    = 0x0100,        // =256;  untere    "     "   
   //TEMPB     = 0x0200,        // =512;  Temperatur-Randwerte berechnen
   //CHEMB     = 0x0400,        // =1024; Chemie-Randwerte berechnen  
   OFFSET_LIMIT = 0x0002,
   SLIP_ZERO_TWO_FREE_FACES = 0x0700, //=1792;
   AIR_BY_OFFSET = 0x0800, //=2048
   OUTFLOW_ZERO_TWO_FREE_FACES = 0x0900, //=2304;
   AIR       = 0x1000,        // =4096;   
   // AIR_TO_FLUID = 0x1F00,    // =7936;
   OUTFLOW_BY_8 = 0x0400,       //=1024;
   OUTFLOW     = 0x2000,     // =8192;
   //OUTFLOW_AND_AIR = 0x2000,
   //FLUID_TO_AIR = 0x8000,     // =32768;
   FLUID_BY_OFFSET = 0x7000,   
   AIR_FLUID_BEGIN = 0x3000, // =;
   AIR_FLUID_MIDDLE =0x8000,
   AIR_FLUID_END = 0xD000,
   FLUID        = 0xE000, // = 57344;
   //GIVEN_VALUE  = 0xE800,
   SLIP_BY_8    = 0x1000, 
   SLIP         = 0x8000, 
   INFLOW      = 0xF000,  // = 61440;
   
};

enum ConvectiveType {DonorCell, QUICK, HLPA, SMART, VONOS};
class Scene;

#include "list.h"

class Scene//Class Scene includes all variables and methods important 
{          //for complete physical and geometrical scene description 
   public:
      double t;//time
      int gridp[3];//number of gridpoints in each co-ordinate direction
      double dimension[3];//physical domain length in each co-ordinate direction  
      int itermax;//maximal number of iterations for solving the poisson equation
      int timesteps;//number of calculated timesteps     
      int timestepmethod;//timestepmethod needed for Adams-Bashfort time discretization, since first step is Euler
      int ObstacleCount;//total number of obstacle cells     
      double delt;//single actual time step 
      double delt_old;//single previous time step     

      double eps;//accuracy threshold for residual of the poisson iteration      
      double omg;//relaxation paramameter for SOR, SSOR, Red-Black and 7color poisson solver scheme      
      double alpha;//donor-cell upwind parameter for velocity in momentum equations     
      double alphatg;//donor-cell upwind parameter for velocity in transport equation
      double tfdiff;//CFL-number for diffusion       
      double  tfconv;//CFL-number for convection       
      double g[3];//volume forces in x,y- and z-direction     
      double nu; // kinematic viscosity (nu=1/re)     
      double re; // reynolds number (re=1/nu)     
      unsigned int TimeDis; // time diskretisation type (Euler or Adams-Bashfort or Runge-Kutta)
      unsigned int Solver; // solver type for poisson equation (SOR, Red-Black or BiCGStab with Jacobi preconditioneer)
      ConvectiveType       Convective; // convective terms handling (VONOS, SMART, HLPA, QUICK or Donor Cell (DC))
      unsigned int GC; // number of ghostcells for convective terms 1 or 2 gc
      double deltmax; // maximal timestep size     
      double TempRef; // reference temperature for Boussinesq-Approximation       
     
      double froude;// dimensionless froude number = V/c where V is a characteristic velocity , and c is a characteristic water wave propagation velocity. 
      //The Froude number is thus the hydrodynamic equivalent to the Mach number = v_o/v_s onde v_o is the velocity of the object relative to the medium and 
      //v_s is the velocity of sound in the medium     
      double* d[3];// gridspacings for pressure cells       
      double* dm[3];//(DX[i]+DX[i-1])/2 
      double* kabs[3];//absolute coordinates     
      double* ddstar[3][3];//3 pt stars second derivative for coordinates x,y,z; weights l(eft),m(iddle),r(ight)
      double* ddPstar[3][3];//3 pt stars second derivative for coordinates x,y,z; weights l(eft),m(iddle),r(ight)  
      double* ddSstar[3][3];//3 pt stars second derivative for coordinates x,y,z; weights l(eft),m(iddle),r(ight)  
      double* ddiv[2][3];//ddiv[0][i][j]=d[i][j+1]/d[i][j], ddiv[1][i][j]=d[i][j-1]/d[i][j]      
      unsigned int periodbound; // periodic boundaries (000000...000ZYX bitwise)
      Scene(); // default constructor
      ~Scene (); // default destructor
      void DumpInfo(FILE* out);//prints object info to out     
      void Init();//init kabs,...  
      void DeleteAll();
};

#define PI 3.14159265358979323846264338327950288

#define ISFLUID(flag)     (flag/OFFSET_LIMIT == FLUID_BY_OFFSET)
//#define ISMOFLUID(flag)    (flag >= FLUID)
#define ISSLIP(flag)       ((flag/8 == SLIP_BY_8) || (flag == SLIP_ZERO_TWO_FREE_FACES))
#define ISNOTSLIP(flag)    ((flag/8 != SLIP_BY_8) || (flag != SLIP_ZERO_TWO_FREE_FACES))
#define ISGIVEN(flag)      ((flag ==INFLOW) || (ISSLIP(flag)))
#define ISNOTGIVEN(flag)   ((flag !=INFLOW) && ((flag/8) != SLIP_BY_8) && (flag != SLIP_ZERO_TWO_FREE_FACES)) 
#define IFFLUID(flag)     if(ISFLUID(flag))
//#define IFMOFLUID(flag)   if(ISMOFLUID(flag))
//#define IFNOFLUID(flag)   if(((flag)&AIR)==AIR)
#define ISOUTFLOW(flag) (((flag/8)==OUTFLOW_BY_8)||(flag==OUTFLOW_ZERO_TWO_FREE_FACES))
#define ISAIR_OUTFLOW(flag) ((ISAIR(flag)) || (ISOUTFLOW(flag)))
#define IFAIR_OUTFLOW(flag)  if(ISAIR_OUTFLOW(flag))
#define ISNOTAIR_OUTFLOW(flag)  (!(ISAIR_OUTFLOW(flag)))
#define ISFLUID_OUTFLOW(flag) ( ISFLUID(flag) || (ISOUTFLOW(flag)))
#define IFFLUID_OUTFLOW(flag) if(ISFLUID_OUTFLOW(flag))
#define ISAIR(flag) (flag/OFFSET_LIMIT == AIR_BY_OFFSET)
#define ISNOTAIR(flag)  (!(ISAIR(flag)))
#define ISNOTSLIP_AIR(flag) ((ISNOTSLIP(flag)) && (ISNOTAIR(flag)))
#define IFAIR(flag) if(ISAIR(flag))
#define ISFLUID_INFLOW(flag) ((ISFLUID(flag))|| (flag==INFLOW))
#define IFFLUID_INFLOW(flag) if((ISFLUID(flag))|| (flag==INFLOW))
//#define IFAIR(flag)  if(((flag)&AIR)==AIR)
#define IFBORDER(flag)    if(FREECELLS(flag)!=0)
#define AIRTYPE(flag)((flag)&(SLIP|INOUT))
#define FREECELLS(flag)   ((flag)&(NORTH|SOUTH|WEST|EAST|TOP|BOTTOM)) 

#define INOUTTYP(flag)    (((flag)&(INOUTTYP2|INOUTTYP3))/INOUTTYP2)
#define IFINOUTTYP1(flag)   if((((flag)/INOUTTYP2)&3) ==0)
#define IFINOUTTYP2(flag)   if((((flag)/INOUTTYP2)&3) ==1)

#define DX S.d[0]
#define DY S.d[1]
#define DZ S.d[2]
#define DXM S.dm[0]
#define DYM S.dm[1]
#define DZM S.dm[2]


#define ILOOP       for(i=1;i<=S.gridp[0];i++)
#define JLOOP       for(j=1;j<=S.gridp[1];j++)
#define KLOOP       for(k=1;k<=S.gridp[2];k++)
#define IJKLOOP ILOOP JLOOP KLOOP

#define IALLLOOP    for(i=0;i<=S.gridp[0]+1;i++)
#define JALLLOOP    for(j=0;j<=S.gridp[1]+1;j++)
#define KALLLOOP    for(k=0;k<=S.gridp[2]+1;k++)
#define IJKALLLOOP IALLLOOP JALLLOOP KALLLOOP


#define INBORDER(i,j,k) ((i<=S.gridp[0]) && (i>0) && (j<=S.gridp[1]) && (j>0) && (k<=S.gridp[2]) && (k>0))
#define INABORDER(i,j,k) (((i)<=S.gridp[0]+1) && ((i)>=0) && ((j)<=S.gridp[1]+1) && ((j)>=0) && ((k)<=S.gridp[2]+1) && ((k)>=0))

#define NOBORDERX(i,j,k) (((i)>=(((1==1)&& !(S.periodbound&1))? 2:0))  &&  ((i)<=(((S.gridp[0]==S.gridp[0])&& !(S.periodbound&1))? (S.gridp[0]-2):(S.gridp[0])))  &&  ((j)>1)  &&  ((j)<S.gridp[1])  &&  ((k)>1)  &&  ((k)<S.gridp[2]))
#define NOBORDERY(i,j,k) (((i)>1)  &&  ((i)<S.gridp[0])  &&  ((j)>=(((1==1)&& !(S.periodbound&2))? 2:0))  &&  ((j)<=(((S.gridp[1]==S.gridp[1])&& !(S.periodbound&2))?(S.gridp[1]-2):(S.gridp[1])))  &&  ((k)>1)  &&  ((k)<S.gridp[2]))
#define NOBORDERZ(i,j,k) (((i)>1)  &&  ((i)<S.gridp[0])  &&  ((j)>1)  &&  ((j)<S.gridp[1])  &&  ((k)>=(((1==1)&& !(S.periodbound&4))? 2:0))  &&  ((k)<=(((S.gridp[2]==S.gridp[2])&& !(S.periodbound&4))?(S.gridp[2]-2):(S.gridp[2]))))
#define NOBORDER(i,j,k)  (((i)>=(((1==1)&& !(S.periodbound&1))? 2:1))  &&  ((i)<=(((S.gridp[0]==S.gridp[0])&& !(S.periodbound&1))?(S.gridp[0]-1):S.gridp[0]))  &&  ((j)>=(((1==1)&& !(S.periodbound&2))? 2:1))  &&  ((j)<=(((S.gridp[1]==S.gridp[1])&& !(S.periodbound&2))?(S.gridp[1]-1):S.gridp[1]))  &&  ((k)>=(((1==1)&& !(S.periodbound&4))? 2:1))  &&  ((k)<=(((S.gridp[2]==S.gridp[2])&& !(S.periodbound&4))?(S.gridp[2]-1):S.gridp[2])))

#define IAL for(i=(((1)&~1)+1);i<=S.gridp[0];i+=2)
#define JAL for(j=(((1)&~1)+1);j<=S.gridp[1];j+=2)
#define KAL for(k=(((1)&~1)+1);k<=S.gridp[2];k+=2)
#define IBL for(i=((1+1)&~1);i<=S.gridp[0];i+=2)
#define JBL for(j=((1+1)&~1);j<=S.gridp[1];j+=2)
#define KBL for(k=((1+1)&~1);k<=S.gridp[2];k+=2)

#define IALB for(i=(((S.gridp[0]+1)&~1)-1);i>=1;i-=2)
#define JALB for(j=(((S.gridp[1]+1)&~1)-1);j>=1;j-=2)
#define KALB for(k=(((S.gridp[2]+1)&~1)-1);k>=1;k-=2)
#define IBLB for(i=((S.gridp[0])&~1);i>=1;i-=2)
#define JBLB for(j=((S.gridp[1])&~1);j>=1;j-=2)
#define KBLB for(k=((S.gridp[2])&~1);k>=1;k-=2)

#endif
